`ifndef COMMON_LIB_SVH
`define COMMON_LIB_SVH
class common_lib;
    // x8 + x2 + x + 1
    // 初始值：00
    // 结果异或值：00
    // 输入反转：false
    // 输出反转：false
    extern function byte crc8(byte data[], int len);

    // 累加后
    extern function byte check_sum(byte data[], int len);

    /* usage:
        int period = 1000;
        int duty = 50;
        common_lib user_lib;
        logic                   trg = 0;
        initial
        begin
            #3us;
            user_lib.pwm(trg, period, duty);
        end
    */
    extern task pwm(ref logic data_in, int period, int duty);

    /*
        以base信号为参考，延迟delay ns时间
        产生num个以period为周期，duty为高电平时间的脉冲信号

        initial
        begin
            automatic int delay = 60;
            automatic int period = 100;
            automatic int duty = 50;
            automatic int num = 3;
            #2.9us;
            user_lib.pulse(stop, trg, delay, period, duty, num);
        end
    */
    extern task pulse(ref logic data_in, ref logic base, int delay, int period, int duty, int num);

endclass

function byte common_lib::check_sum(byte data[], int len);
begin
    byte result = 0;
    for(int i = 0; i < len; i++)
    begin
        result = result + data[i];
    end

    return result;
end
endfunction

function byte common_lib::crc8(byte data[], int len);
byte crc = 0;
byte m = 0;

while(len--)
begin
    crc ^= data[m];
    for(int i = 0; i < 8; i = i + 1 )
    begin
        if(crc & 8'h80)
            crc = (crc << 1) ^ 8'h07;
        else 
            crc <<= 1;
    end
    m = m + 1;
end
return crc;
endfunction


task common_lib::pwm(ref logic data_in, int period, int duty);
repeat(10000)
begin
    int high = period * duty/100;
    int low = period * (100 - duty)/100;
    repeat(high)
    begin
        data_in = 1; #1ns;
    end
    repeat(low)
    begin
        data_in = 0; #1ns;
    end
end
endtask

task common_lib::pulse(ref logic data_in, ref logic base, int delay, int period, int duty, int num);

    int high = period * duty/100;
    int low = period * (100 - duty)/100;

    repeat(10000)
    begin
        @(posedge base);
        repeat(delay)
        begin
            #1ns;
        end

        repeat(num)
        begin
            repeat(high)
            begin
                data_in = 1; #1ns;
            end
            repeat(low)
            begin
                data_in = 0; #1ns;
            end
        end
    end

endtask

`endif

